<?php
def("amicitia/persistencia/daos/","DaoJuego");
def("amicitia/persistencia/daos/","ConexionBD");
def("amicitia/persistencia/excepciones/","IntegridadDatosException");
def("amicitia/modelo/entidades/","Juego");
def("amicitia/modelo/ejecucion/reglas/","ReglaAnoPasado");
def("amicitia/modelo/ejecucion/reglas/","ReglaParejaImposible");

/**
 * Maneja todas las consideraciones de persistencia en MySql para con la
 * entidad Juego.
 * 
 * @author Willy A. Kuster
 */
class DaoJuegoMySql implements DaoJuego {
	
	const SELECT_JUEGO = "SELECT id, ocasion, fecha, reglas, estatus, esvisible, id_grupo_fk FROM juego WHERE id=%s";
	const INSERT_JUEGO = "INSERT juego (id,ocasion,fecha,reglas,estatus,esvisible,id_grupo_fk) VALUES (%s,%s,%s,%s,%s,%s,%s)";
	const INSERT_JUEGO_PERSONA = "INSERT juego_persona (id_juego_fk,id_persona_fk) VALUES (%s,%s)";
	const DELETE_JUEGO = "DELETE FROM juego WHERE id=%s";
	
	const SELECT_JUEGO_PASADO = "SELECT id FROM juego WHERE id_grupo_fk=%s AND fecha<'%s' ORDER BY fecha DESC LIMIT 1";
	const SELECT_JUEGO_PERSONA = "SELECT id_persona_fk FROM juego_persona WHERE id_juego_fk=%s";
	const SELECT_JUEGO_PAREJA = "SELECT id_pareja_fk FROM juego_pareja WHERE id_juego_fk=%s";
	const SELECT_JUEGO_REGALANTES = "SELECT id_persona_fk FROM juego_regalante WHERE id_juego_fk=%s FOR UPDATE";
	const SELECT_JUEGO_REGALADOS = "SELECT id_persona_fk FROM juego_regalado WHERE id_juego_fk=%s FOR UPDATE";
	const SELECT_JUEGO_DESEO = "SELECT id FROM deseo WHERE id_juego_fk=%s";
	const SELECT_JUEGO_QUINIELA = "SELECT id FROM quiniela WHERE id_juego_fk=%s";
	
	public function __construct() {
		$this->conexion = ConexionBD::getConexionBD();
		//$this->conexion->conectar();
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#obtenerJuego($id)
	 */
	function obtenerJuego($id) {
		$id = $this->conexion->escaparCadena($id);
		$query = sprintf(self::SELECT_JUEGO,$id);
		$result = $this->conexion->seleccionar($query);

		if($obj = $result->fetch_object()){
			$juego = new Juego();
			$juego->setId($obj->id);
			$juego->setOcasion($obj->ocasion);
			$juego->setFecha($obj->fecha);
			$var=unserialize($obj->reglas);
			$juego->setReglas(unserialize($obj->reglas));
			$juego->setEstatus($obj->estatus);
			$juego->setEsVisible((bool)$obj->esvisible);
			
			$fabricaDao = FabricaDao::obtenerFabrica();
			$daoGrupo = $fabricaDao->obtenerDaoGrupo();	

			$juego->setGrupo($daoGrupo->obtenerGrupo($obj->id_grupo_fk));
			
			$juego->setJugadores(NULL);//inicialización Lazy.
			$juego->setParejas(NULL);//inicialización Lazy.
			$juego->setRegalados(NULL);//inicialización Lazy.
			$juego->setRegalantes(NULL);//inicialización Lazy.
			$juego->setDeseos(NULL);//inicialización Lazy.
			$juego->setQuinielas(NULL);//inicialización Lazy.

			$result->close();

			return $juego;
		} else {
			return NULL;
		}
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#obtenerJuegoPasado($juego)
	 */
	function obtenerJuegoPasado(Juego $juego){
		$id_grupo_fk = $this->conexion->escaparCadena($juego->getGrupo()->getId());
		$fecha = $this->conexion->escaparCadena($juego->getFecha());
		$query = sprintf(self::SELECT_JUEGO_PASADO,$id_grupo_fk,$fecha);
		$result = $this->conexion->seleccionar($query);
		
		$obj = $result->fetch_object();
		$juegoPasado = $this->obtenerJuego($obj->id);
		
		return $juegoPasado;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#cargarJugadores($juego)
	 */
	function cargarJugadores(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_PERSONA,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPersona = $fabricaDao->obtenerDaoPersona();	
		
		$listaJugadores = array();
		while ($obj = $result->fetch_object()) {
			$listaJugadores[$obj->id_persona_fk] = $daoPersona->obtenerPersona($obj->id_persona_fk);
		}
		
		$juego->setJugadores($listaJugadores);
		return $juego;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#cargarParejas($juego)
	 */
	function cargarParejas(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_PAREJA,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPareja = $fabricaDao->obtenerDaoPareja();	
		
		$listaParejas = array();
		while ($obj = $result->fetch_object()) {
			$listaParejas[$obj->id_pareja_fk] = $daoPareja->obtenerPareja($obj->id_pareja_fk);
		}
		
		$juego->setParejas($listaParejas);
		return $juego;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#cargarRegalados($juego)
	 */
	function cargarRegalados(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_REGALADOS,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPersona = $fabricaDao->obtenerDaoPersona();	
		
		$listaRegalados = array();
		while ($obj = $result->fetch_object()) {
			$listaRegalados[$obj->id_persona_fk] = $daoPersona->obtenerPersona($obj->id_persona_fk);
		}
		
		$juego->setRegalados($listaRegalados);
		return $juego;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#cargarRegalantes($juego)
	 */
	function cargarRegalantes(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_REGALANTES,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoPersona = $fabricaDao->obtenerDaoPersona();	
		
		$listaRegalantes = array();
		while ($obj = $result->fetch_object()) {
			$listaRegalantes[$obj->id_persona_fk] = $daoPersona->obtenerPersona($obj->id_persona_fk);
		}
		
		$juego->setRegalantes($listaRegalantes);
		return $juego;
	}
	
	/*/
	 * @see persistencia/daos/DaoJuego#cargarDeseos($juego)
	 */
	function cargarDeseos(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_DESEO,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoDeseo = $fabricaDao->obtenerDaoDeseo();	
		
		$listaDeseos = array();
		while ($obj = $result->fetch_object()) {
			$listaDeseos[$obj->id] = $daoDeseo->obtenerDeseo($obj->id);
		}
		
		$juego->setDeseos($listaDeseos);
		return $juego;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#cargarQuinielas($juego)
	 */
	function cargarQuinielas(Juego $juego){
		$id = $this->conexion->escaparCadena($juego->getId());
		$query = sprintf(self::SELECT_JUEGO_QUINIELA,$id);
		$result = $this->conexion->seleccionar($query);
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoQuiniela = $fabricaDao->obtenerDaoQuiniela();	
		
		$listaQuinielas = array();
		while ($obj = $result->fetch_object()) {
			$listaQuinielas[$obj->id] = $daoQuiniela->obtenerQuiniela($obj->id);
		}
		
		$juego->setQuinielas($listaQuinielas);
		return $juego;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#guardarJuego($juego)
	 */
	function guardarJuego(Juego $juego) {
		
		$this->verificarJuego($juego);
		
		$id = is_null($juego->getId()) ? "NULL" : (int)$this->conexion->escaparCadena($juego->getId());
		$ocacion = "'".$this->conexion->escaparCadena($juego->getOcasion())."'";
		$fecha = is_null($juego->getFecha()) ? "CURDATE()" : "'".$this->conexion->escaparCadena($juego->getFecha())."'";
		$reglas = "'".$this->conexion->escaparCadena(serialize($juego->getReglas()))."'";
		$estatus = (int)$this->conexion->escaparCadena($juego->getEstatus());
		$esVisible = "'".$this->conexion->escaparCadena($juego->getEsVisible())."'";
		
		$fabricaDao = FabricaDao::obtenerFabrica();
		$daoGrupo = $fabricaDao->obtenerDaoGrupo();
		
		$idGrupo = is_null($juego->getGrupo()->getId()) ? 
			$daoGrupo->guardarGrupo($juego->getGrupo()) : 
			(int)$this->conexion->escaparCadena($juego->getGrupo()->getId());
		
		$query = sprintf(self::INSERT_JUEGO,$id,$ocacion,$fecha,$reglas,$estatus,$esVisible,$idGrupo);
		$id = $this->conexion->insertar($query);
		
		if(count($juego->getJugadores())>0){
			$fabricaDao = FabricaDao::obtenerFabrica();
			$daoPersona = $fabricaDao->obtenerDaoPersona();	
			
			foreach ($juego->getJugadores() as $jugador) {
				$idJugador = (int)$this->conexion->escaparCadena($jugador->getId());
				$query = sprintf(self::INSERT_JUEGO_PERSONA,$id,$idJugador);
				$this->conexion->insertar($query);
			}
		}
		
		return $id;
	}
	
	/**
	 * @see persistencia/daos/DaoJuego#eliminarJuego($id)
	 */
	function eliminarJuego($id) {
		$id = $this->conexion->escaparCadena($id);
		$query = sprintf(self::DELETE_JUEGO,$id);
		$afectados = $this->conexion->actualizarOEliminar($query);
		
		if ($afectados==1) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Verifica la integridad del objeto Juego que se pase por parámetro.
	 * 
	 * @param $juego
	 * 			Un objeto Juego.
	 */
	private function verificarJuego(Juego $juego) {
		if(is_null($juego->getOcasion()) || $juego->getOcasion()=="")
			throw new IntegridadDatosException(get_class($juego),"ocasion",$juego->getOcasion());
		if(is_null($juego->getEstatus()) || ($juego->getEstatus()!=Estatus::ACTIVO && $juego->getEstatus()!=Estatus::CREACION && $juego->getEstatus()!=Estatus::CULMINADO))
			throw new IntegridadDatosException(get_class($juego),"estatus",$juego->getEstatus());
		if(is_null($juego->getEsVisible()))
			throw new IntegridadDatosException(get_class($juego),"esVisible",$juego->getEsVisible());
		if(is_null($juego->getGrupo()))
			throw new IntegridadDatosException(get_class($juego),"grupo",$juego->getGrupo());
		if(count($juego->getJugadores())<0)
			throw new IntegridadDatosException(get_class($juego),"jugadores",$juego->getJugadores());
	}
	
}
?>